/**
 * Copyright (c) 2011 Basil Shikin, VintageRadio Project
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.vintagephone.model.podcaster;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;

import android.util.Log;

/**
 * This task is used to download lastet edition of the podcast into specified folder.
 * 
 * @author Basil Shikin
 *
 */
class PodcastDownloadTask
    implements Runnable
{

    private static final String Tag = "PodcastDownloadTask";
    
    private final String m_sourceUrl;
    private final File m_targetFolder;
    
    private final byte[] m_buffer = new byte[ 50*1024 ];
    
    public PodcastDownloadTask(String sourceUrl, File targetFolder)
    {
        m_sourceUrl = sourceUrl;
        m_targetFolder = targetFolder;
    }

    @Override
    public void run()
    {
        
        try
        {
            final String podcastXml = readPodcastXml();
            Log.i( Tag, "Read podcast XML (" + podcastXml.length() + " bytes" );
            
            final String downloadUrl = parseDownloadUrl( podcastXml );
            Log.i( Tag, "Last podcast item located at \"" + downloadUrl + "\"" );
            
            cleanOldPodcastFiles();
            
            final File destinationFile = createDestinationFile( downloadUrl );
            downloadToFile( downloadUrl, destinationFile );
            Log.i( Tag, "Last podcast downloaded to \"" + destinationFile.getAbsolutePath() + "\"" );
        } 
        catch (IOException e)
        {
            Log.e( Tag, "Unable to read podcast", e );
        }
    }

    private void cleanOldPodcastFiles()
    {
        final File[] files = m_targetFolder.listFiles( new FilenameFilter() {
            public boolean accept(File dir, String filename)
            {
                return filename.toLowerCase().endsWith(".mp3");
            }
        });
        
        if ( files != null && files.length > 0 )
        {
            for ( File file : files ) 
            {
                final boolean deleted = file.delete();
                if ( !deleted ) Log.w( Tag, "Unable to delete " + file.getAbsolutePath() );
            }
        }
    }
    

    private void downloadToFile(String downloadUrl, File destinationFile) throws IOException
    {
        final URL podcastXml = new URL( downloadUrl );
        
        InputStream podcastStream = null;
        OutputStream fileStream   = null;
        try
        {
            podcastStream = podcastXml.openStream();
            fileStream = new FileOutputStream( destinationFile );
            
            int read = podcastStream.read( m_buffer );
            int totalRead = read;
            int printCounter = 0;
            
            while ( read > 0 )
            {
                fileStream.write( m_buffer, 0, read );
                
                read = podcastStream.read( m_buffer );
                
                totalRead += read;
                
                if ( totalRead > printCounter * 500*1024 )
                {
                    Log.d( Tag, "Reading podcast, so far " + totalRead/1024 + " Kb");
                    printCounter += 1;
                }
            }
            
            Log.d( Tag, "Podcast read. Total " + totalRead/(1024*1024) + " Mb");
        }
        finally
        {
            if ( podcastStream != null ) podcastStream.close();
            if ( fileStream != null ) fileStream.close();
        }
    }

    private File createDestinationFile(String downloadUrl) throws IOException
    {
        final int slashIx = downloadUrl.lastIndexOf('/');
        
        if ( slashIx > 0  )
        {
            final String fileName = downloadUrl.substring( slashIx );
            
            final File result = new File( m_targetFolder, fileName );
            if ( result.exists() )
            {
                final boolean deleted = result.delete();
                if ( !deleted ) Log.w( Tag, "Unable to delete " + result.getAbsolutePath() );
            }
            else
            {
                result.createNewFile();
            }
            
            return result;
        }
        else
        {
            throw new IllegalArgumentException("Malformed podcast URL: " + downloadUrl );
        }
    }

    private String parseDownloadUrl(String podcastXml)
    {
        final int itemIx = podcastXml.indexOf("<item>");
        if ( itemIx > 0 )
        {
            final int enclosureIx = podcastXml.indexOf("<enclosure", itemIx );
            if ( enclosureIx > 0 )
            {
                final String urlAttr = "url=\"";
                final int urlStart = podcastXml.indexOf( urlAttr, enclosureIx );
                final int urlEnd   = podcastXml.indexOf( "\"", urlStart + urlAttr.length() + 1);
                
                if ( urlStart > 0 && urlEnd > urlStart )
                {
                    return podcastXml.substring( urlStart + urlAttr.length(), urlEnd );
                }
                else
                {
                    Log.e( Tag, "No url start and end found in podcast XML");
                }
            }
            else
            {
                Log.e( Tag, "No <enclosure> found in podcast XML");
            }
        }
        else
        {
            Log.e( Tag, "No <item> found in podcast XML");
        }
        
        return null;
    }

    private String readPodcastXml() throws IOException
    {
        final URL podcastXml = new URL( m_sourceUrl );
        
        final StringBuffer result = new StringBuffer();
        
        InputStream podcastStream = null;
        BufferedReader podcastReader = null;     
        try
        {
            podcastStream = podcastXml.openStream();
            podcastReader = new BufferedReader( new InputStreamReader( podcastStream ) );
            
            String inputLine;
            while ( (inputLine = podcastReader.readLine()) != null)
            {
                result.append( inputLine );
            }

        }
        finally
        {
            if ( podcastStream != null ) podcastStream.close();
            if ( podcastReader != null ) podcastReader.close();
        }
        
        return result.toString();
    }
}
